import React, {DependencyList, useCallback, useState} from 'react';
import {ApiResult} from "@/utils/data";
import {message} from "antd";
import {MessageType} from "antd/lib/message";
import {newDelay} from "@/utils/utils";

/** 编辑组件返回值 */
export interface EditOperate<T> {
  /** 是否新建 */
  created: boolean;
  /** 表示提交操作是否正在进行中 */
  submitLoading: boolean;
  /** 组件是否显示 */
  editVisible: boolean;
  /** 编辑的数据 */
  editModel: T;
  /** 新建函数 */
  handleCreate: (record?: Partial<T>) => void;
  /** 编辑函数 */
  handleEdit: (record: T) => void;
  /** 提交函数 */
  handleSubmit: (_isCreate: boolean, oldRecord: Partial<T> | undefined, newRecord: T) => void;
  /** 编辑取消函数 */
  handleCancel: () => void;
}

/** 编辑组件属性 */
export interface EditProps<T> {
  /** 编辑数据时读取数据的提示消息 */
  loadingMessage?: React.ReactNode;
  /** 提交进行中提示消息 */
  operateMessage?: React.ReactNode;
  /** 提交操作成功后的提示消息 */
  submitSuccessMessage?: React.ReactNode;
  /** 新建对象 */
  onCreate?: () => Partial<T> | undefined;
  /** 修改对象 */
  onEdit?: (record: T) => Promise<ApiResult<T>>;
  /** 提交对象 */
  onSubmit?: (_isCreate: boolean, oldRecord: Partial<T> | undefined, newRecord: T) => Promise<ApiResult>;
  /** 提交成功后的回调函数 */
  onSubmitSucess?: () => void;
  /** 组件依赖项 */
  deps?: DependencyList;
}

/** 编辑操作组件 */
function useEdit<Model>(props: EditProps<Model> = {}): EditOperate<Model> {
  const options: EditProps<Model> = {};
  const deps = props.deps || [];
  options.loadingMessage = props.loadingMessage || '正在加载...';
  options.operateMessage = props.operateMessage || '正在保存...';
  options.submitSuccessMessage = props.submitSuccessMessage || '保存操作成功';
  options.onCreate = props.onCreate;
  options.onEdit = props.onEdit;
  options.onSubmit = props.onSubmit;
  options.onSubmitSucess = props.onSubmitSucess;

  const [created, setCreated] = useState<boolean>(false);
  const [submitLoading, setSubmitLoading] = useState(false);
  const [editVisible, setEditVisible] = useState<boolean>(false);
  const [editModel, setEditModel] = useState<Partial<Model>>();

  /** 新建函数 */
  const handleCreate = useCallback((record?: Partial<Model>) => {
    //设置新建状态为true
    setCreated(true);
    //设置编辑的数据
    setEditModel((record || (options.onCreate && options.onCreate()) || {}));
    //设置组件显示状态为true
    setEditVisible(true);
  }, deps);

  /** 编辑函数 */
  const handleEdit = useCallback((record: Model) => {
    if (!options.onEdit) return;

    let hideMessage: MessageType;
    const delay = newDelay();//创建延迟对象,目的是当后台请求很快的时候,可以不显示操作提示
    //默认延迟500毫秒才显示操作提示
    delay.run(() => hideMessage = message.loading(options.loadingMessage));
    options.onEdit(record)?.then(r => {
      delay.finish(() => hideMessage && hideMessage());
      if (r.success && r.data) {
        // 读取成功后设置数据对象
        // 设置为编辑模式
        setCreated(false);
        //设置编辑的数据
        setEditModel(r.data);
        //设置组件显示状态为true
        setEditVisible(true);
      }
    }).catch(() => delay.finish(() => hideMessage && hideMessage()));
  }, deps);

  /** 提交函数  */
  const handleSubmit = useCallback((_isCreate: boolean, oldRecord: Partial<Model> | undefined, newRecord: Model) => {
    if (!options.onSubmit) return;

    const key = Date.now();
    let hideMessage: MessageType;
    const delay = newDelay();
    //创建延迟对象,目的是当后台请求很快的时候,可以不显示操作提示
    //设置提交状态为true
    setSubmitLoading(true);
    //默认延迟500毫秒才显示操作提示
    delay.run(() => hideMessage = message.loading(options.operateMessage, key));
    const record = {...oldRecord, ...newRecord};
    // @ts-ignore
    props.onSubmit(_isCreate, oldRecord, record)?.then(r => {
      delay.finish(() => hideMessage && hideMessage());
      //设置提交状态为false
      setSubmitLoading(false);
      if (r.success) {
        //操作成功后进行消息提示
        message.success({content: options.submitSuccessMessage, key, duration: 1});
        //提交成功后执行成功回调函数
        options?.onSubmitSucess && options.onSubmitSucess();
        //设置组件显示状态为false,关闭编辑组件
        setEditVisible(false);
      }
    }).catch(() => {
      setSubmitLoading(false);
      delay.finish(() => hideMessage && hideMessage());
    });
  }, deps);

  /** 编辑取消函数 */
  const handleCancel = useCallback(() => {
    //设置组件显示状态为false
    setEditVisible(false);
  }, deps);


  return {
    created,
    submitLoading,
    editVisible,
    // @ts-ignore
    editModel,
    handleCreate,
    handleEdit,
    handleSubmit,
    handleCancel,
  };
}

export default useEdit;

